home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / pmake / customs / import.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-11-15  |  20.6 KB  |  766 lines

  1. /*-
  2.  * import.c --
  3.  *    Functions to import processes.
  4.  *
  5.  * Copyright (c) 1988, 1989 by the Regents of the University of California
  6.  * Copyright (c) 1988, 1989 by Adam de Boor
  7.  * Copyright (c) 1989 by Berkeley Softworks
  8.  *
  9.  * Permission to use, copy, modify, and distribute this
  10.  * software and its documentation for any non-commercial purpose
  11.  * and without fee is hereby granted, provided that the above copyright
  12.  * notice appears in all copies.  The University of California,
  13.  * Berkeley Softworks and Adam de Boor make no representations about
  14.  * the suitability of this software for any purpose.  It is provided
  15.  * "as is" without express or implied warranty.
  16.  */
  17. #ifndef lint
  18. static char *csid =
  19. "$Id: import.c,v 1.23 89/11/14 13:46:05 adam Exp $ SPRITE (Berkeley)";
  20. #endif lint
  21.  
  22. #include    "customsInt.h"
  23. #include    "lst.h"
  24. #include    "log.h"
  25. #include    <sys/types.h>
  26. #include    <sys/signal.h>
  27. #include    <sys/wait.h>
  28. #include    <sys/resource.h>
  29. #include    <sys/file.h>
  30. #include    <stdio.h>
  31. #include    <varargs.h>
  32.  
  33. /*
  34.  * Permits published by the MCA are kept in ImportPermit structures on the
  35.  * permits list until a process actually arrives for them. If one doesn't
  36.  * arrive before the expiration timer goes off, the ImportPermit (and hence
  37.  * the ExportPermit) is discarded.
  38.  */
  39. typedef struct {
  40.     ExportPermit  permit;       /* Actual permit from MCA */
  41.     Rpc_Event      expire;       /* Expiration timer. If this goes off,
  42.                  * the permit gets nuked */
  43. } ImportPermit;
  44.  
  45. /*
  46.  * A Process structure is assigned to each imported process so it can be
  47.  * killed, its status returned, etc. The ExportPermit for the job is also
  48.  * saved to allow the log server to match a job finish with a start.
  49.  */
  50. typedef struct {
  51.     int                  pid;            /* ID of child */
  52.     ImportPermit      *permit;      /* Import permit for job */
  53.     struct sockaddr_in     retAddr;      /* Address of socket on which to
  54.                      * return the exit status */
  55. } Process;
  56.  
  57. static Lst            permits;    /* List of permits awaiting processes */
  58. static Lst            imports;    /* List of active processes */
  59.  
  60. /*
  61.  * Once processes are running, we check them every checkInterval seconds.
  62.  * This should probably be changed to catch SIGCHLD and set an event to be
  63.  * taken immediately control returns to Rpc.
  64.  */
  65. static Rpc_Event      checkEvent;
  66. static struct timeval    checkInterval = {
  67.     1, 0,
  68. };
  69.  
  70. /*
  71.  * This is the time for which an ImportPermit may remain active without a
  72.  * process.
  73.  */
  74. static struct timeval     expirationDate = {
  75.     30, 0,
  76. };
  77.  
  78. static Boolean ImportCheckAll();
  79.  
  80.  
  81. /*-
  82.  *-----------------------------------------------------------------------
  83.  * ImportCmpPid --
  84.  *    Callback function for ImportCheckAll to find a Process record
  85.  *    with the given pid.
  86.  *
  87.  * Results:
  88.  *    0 if it matches, non-0 if it doesn't.
  89.  *
  90.  * Side Effects:
  91.  *    None.
  92.  *
  93.  *-----------------------------------------------------------------------
  94.  */
  95. static int
  96. ImportCmpPid(procPtr, pid)
  97.     Process           *procPtr;       /* Process to examine */
  98.     int                  pid;            /* PID desired. */
  99. {
  100.     return (procPtr->pid - pid);
  101. }
  102.     
  103. /*-
  104.  *-----------------------------------------------------------------------
  105.  * ImportHandleKill --
  106.  *    Handle the killing of an imported process.
  107.  *
  108.  * Results:
  109.  *    None.
  110.  *
  111.  * Side Effects:
  112.  *    The signal number is read from the socket and given to the child.
  113.  *
  114.  *-----------------------------------------------------------------------
  115.  */
  116. static void
  117. ImportHandleKill (from, msg, len, data)
  118.     struct sockaddr_in        *from;
  119.     Rpc_Message              msg;
  120.     int                      len;
  121.     Rpc_Opaque               data;
  122. {
  123.     Kill_Data              *packet = (Kill_Data *)data;
  124.     register Process           *procPtr;
  125.     LstNode               ln;
  126.     
  127.     /*
  128.      * Find the Process structure corresponding to the id number
  129.      * given, then kill the process.
  130.      */
  131.     if (Lst_Open(imports) == SUCCESS) {
  132.     while ((ln = Lst_Next(imports)) != NILLNODE) {
  133.         procPtr = (Process *)Lst_Datum(ln);
  134.         if (procPtr->permit->permit.id == packet->id) {
  135.         Lst_Close(imports);
  136.         Rpc_Return(msg, 0, (Rpc_Opaque)0);
  137.         if (verbose) {
  138.             printf("killpg(%d, %d)\n", procPtr->pid, packet->signo);
  139.         }
  140.  
  141.         (void)killpg(procPtr->pid, packet->signo);
  142.         Log_Send(LOG_KILL, 2,
  143.              xdr_exportpermit, &procPtr->permit->permit,
  144.              xdr_long, &packet->signo);
  145.         return;
  146.         }
  147.     }
  148.     Lst_Close(imports);
  149.     }
  150.     Rpc_Error(msg, RPC_BADARGS);
  151. }
  152.  
  153. /*-
  154.  *-----------------------------------------------------------------------
  155.  * ImportCheckAll --
  156.  *    Check on all the jobs. This is kinda gross. It just does a wait3
  157.  *    to see if anyone wants to say anything and finishes the job out
  158.  *    if it does.
  159.  *
  160.  * Results:
  161.  *    FALSE.
  162.  *
  163.  * Side Effects:
  164.  *    Jobs will be removed from the imports list, if they actually
  165.  *    finish. If there are no imported jobs left, the event that caused
  166.  *    the invocation of this function is deleted.
  167.  *
  168.  *-----------------------------------------------------------------------
  169.  */
  170. static Boolean
  171. ImportCheckAll()
  172. {
  173.     union wait      status;       /* Status of child */
  174.     int              pid;            /* ID of reporting child */
  175.     LstNode       ln;
  176.     Process       *procPtr;
  177.  
  178.     while ((pid=wait3(&status,WNOHANG|WUNTRACED,(struct rusage *)0)) > 0) {
  179.     ln = Lst_Find (imports, (ClientData)pid, ImportCmpPid);
  180.     if (ln != NILLNODE) {
  181.         procPtr = (Process *)Lst_Datum(ln);
  182.         (void)Lst_Remove(imports, ln);
  183.         if (Lst_IsEmpty (imports)) {
  184.         /*
  185.          * Because ImportProcess may be called while waiting for
  186.          * a reply to the Avail_Send, we want to make sure to
  187.          * delete the event as soon as it is unneeded.
  188.          */
  189.         Rpc_EventDelete(checkEvent);
  190.         }
  191.         Avail_Send();
  192.         free((char *)procPtr->permit);
  193.         free((char *)procPtr);
  194.     }
  195.     }
  196.     return(FALSE);
  197. }
  198.  
  199. /*-
  200.  *-----------------------------------------------------------------------
  201.  * ImportExpire --
  202.  *    Delete an expired ImportPermit.
  203.  *
  204.  * Results:
  205.  *    False.
  206.  *
  207.  * Side Effects:
  208.  *    The permit is removed from the permits list and the event that
  209.  *    caused this call back is deleted. An availability packet is
  210.  *    sent to the mca, too, since this expiration could have made the
  211.  *    host available again.
  212.  *
  213.  *-----------------------------------------------------------------------
  214.  */
  215. static Boolean
  216. ImportExpire(ln)
  217.     LstNode               ln;            /* Node of permit to nuke */
  218. {
  219.     ImportPermit          *permit;    /* The actual permit */
  220.  
  221.     permit = (ImportPermit *)Lst_Datum(ln);
  222.     Rpc_EventDelete(permit->expire);
  223.     Lst_Remove(permits, ln);
  224.     free((char *)permit);
  225.     Avail_Send();
  226. }
  227.  
  228. /*-
  229.  *-----------------------------------------------------------------------
  230.  * ImportAllocated --
  231.  *    Notice that we've been allocated. This call is only allowed to
  232.  *    come from the udp customs port on the master machine (or 127.1
  233.  *     [localhost] if we are the master).
  234.  *
  235.  * Results:
  236.  *    None.
  237.  *
  238.  * Side Effects:
  239.  *    None.
  240.  *
  241.  *-----------------------------------------------------------------------
  242.  */
  243. /*ARGSUSED*/
  244. static void
  245. ImportAllocated(from, msg, len, permit)
  246.     struct sockaddr_in    *from;
  247.     Rpc_Message          msg;
  248.     int                  len;
  249.     ExportPermit      *permit;
  250. {
  251.     ImportPermit      *newPermit;
  252.     AllocReply            reply;
  253.  
  254.     if (len != sizeof(ExportPermit)) {
  255.     Rpc_Error (msg, RPC_BADARGS);
  256.     } else if ((from->sin_port == htons(udpPort)) &&
  257.            ((from->sin_addr.s_addr == masterAddr.sin_addr.s_addr) ||
  258.         (amMaster && Local(from))))
  259.     {
  260.     if (verbose) {
  261.         printf ("Incoming process from %s (id %u)\n",
  262.             InetNtoA(permit->addr), permit->id);
  263.     }
  264.     
  265.     newPermit = (ImportPermit *)malloc (sizeof (ImportPermit));
  266.     newPermit->permit = *permit;
  267.     Lst_AtEnd (permits, (ClientData)newPermit);
  268.     newPermit->expire =
  269.         Rpc_EventCreate(&expirationDate, ImportExpire,
  270.                 (Rpc_Opaque)Lst_Last(permits));
  271.     reply.avail = Avail_Local(AVAIL_EVERYTHING, &reply.rating);
  272.     Rpc_Return(msg, sizeof(reply), (Rpc_Opaque)&reply);
  273.     } else {
  274.     printf ("Attempted Allocation from %d@%s\n",
  275.         ntohs(from->sin_port), InetNtoA(from->sin_addr));
  276.     printf ("Master = %s\n", InetNtoA(masterAddr.sin_addr));
  277.     Rpc_Error(msg, RPC_ACCESS);
  278.     Log_Send(LOG_ACCESS, 1, xdr_sockaddr_in, from);
  279.     }
  280. }
  281.  
  282. /*-
  283.  *-----------------------------------------------------------------------
  284.  * ImportFindID --
  285.  *    Look for a permit with the given id number. Callback procedure
  286.  *    for ImportProcess.
  287.  *
  288.  * Results:
  289.  *    0 if the current permit matches. non-zero otherwise.
  290.  *
  291.  * Side Effects:
  292.  *    None
  293.  *
  294.  *-----------------------------------------------------------------------
  295.  */
  296. static int
  297. ImportFindID (permit, id)
  298.     ImportPermit  *permit;
  299.     u_long        id;
  300. {
  301.     return (permit->permit.id - id);
  302. }
  303.  
  304. /*-
  305.  *-----------------------------------------------------------------------
  306.  * ImportPrintPermit --
  307.  *    Print out a permit...Used by ImportProcess in verbose mode.
  308.  *
  309.  * Results:
  310.  *    Always returns 0.
  311.  *
  312.  * Side Effects:
  313.  *    None.
  314.  *
  315.  *-----------------------------------------------------------------------
  316.  */
  317. static int
  318. ImportPrintPermit (permitPtr)
  319.     ImportPermit  *permitPtr;
  320. {
  321.     printf ("#%u to %s, ", permitPtr->permit.id,
  322.         InetNtoA(permitPtr->permit.addr));
  323.     return (0);
  324. }
  325.  
  326. /*-
  327.  *-----------------------------------------------------------------------
  328.  * ImportExtractVector --
  329.  *    Extract an array of strings from a buffer and return a vector of
  330.  *    char pointers. Used by ImportProcess to get the argv and envp for
  331.  *    the new process.
  332.  *
  333.  * Results:
  334.  *    A dynamically-allocated vector of char *'s.
  335.  *
  336.  * Side Effects:
  337.  *    *strPtrPtr is set to point beyond the extracted strings.
  338.  *
  339.  *-----------------------------------------------------------------------
  340.  */
  341. static char **
  342. ImportExtractVector(strPtrPtr)
  343.     char          **strPtrPtr;
  344. {
  345.     register char *cp;
  346.     register char **vec;
  347.     register int  numStrings;
  348.     char          **vecPtr;
  349.  
  350.     cp = *strPtrPtr;
  351.     numStrings = *(int *)cp;
  352.     vecPtr = (char **)malloc((unsigned)((numStrings + 1) * sizeof(char *)));
  353.     cp += sizeof(int);
  354.     for (vec = vecPtr; numStrings != 0; vec++, numStrings--) {
  355.     *vec = cp;
  356.     cp += strlen(cp) + 1;
  357.     }
  358.     *vec = (char *)0;
  359.     cp = Customs_Align(cp, char *);
  360.     *strPtrPtr = cp;
  361.     return(vecPtr);
  362. }
  363.  
  364. /*-
  365.  *-----------------------------------------------------------------------
  366.  * ImportProcess --
  367.  *    Import a process from another machine. Requires an unique ID
  368.  *    which is communicated by the MCA in the CustomsAlloc call.
  369.  *
  370.  * Results:
  371.  *    None.
  372.  *
  373.  * Side Effects:
  374.  *
  375.  *-----------------------------------------------------------------------
  376.  */
  377. /*ARGSUSED*/
  378. static void
  379. ImportProcess (from, msg, len, wbPtr)
  380.     struct sockaddr_in    *from;
  381.     Rpc_Message          msg;
  382.     int                  len;
  383.     WayBill           *wbPtr;
  384. {
  385.     LstNode           ln;             /* Node of published permit */
  386.     ImportPermit      *permit;        /* The permit itself */
  387.     Process           *proc;            /* Structure to track job */
  388.     int                  sock;            /* I/O socket for job */
  389.     char              *cp;            /* General char pointer */
  390.     char              *cwd;            /* Directory for job */
  391.     char              *file;            /* File to exec */
  392.     char              **argv;            /* Arguments for it */
  393.     char              **envp;            /* Environment for job */
  394.     extern char          **environ;      /* Current environment */
  395.     int                  permituid;      /* UID in permit's ID */
  396.  
  397. #define ERROR(str) Rpc_Return(msg, sizeof("str"), (Rpc_Opaque)"str"); \
  398.                    (void)close(sock);\
  399.                    Rpc_Ignore(sock);\
  400.            return;
  401.  
  402.     sock = Rpc_MessageSocket(msg);
  403.     
  404.     ln = Lst_Find (permits, (ClientData)wbPtr->id, ImportFindID);
  405.     if (ln == NILLNODE) {
  406.     if (verbose) {
  407.         if (Lst_IsEmpty (permits)) {
  408.         printf ("No permits issued\n");
  409.         } else {
  410.         printf ("No permit for %u: ", wbPtr->id);
  411.         Lst_ForEach (permits, ImportPrintPermit, (ClientData)0);
  412.         putchar('\n');
  413.         }
  414.     }
  415.     ERROR(No permit issued to you);
  416.     } else {
  417.     permit = (ImportPermit *)Lst_Datum (ln);
  418.     Rpc_EventDelete(permit->expire);
  419.     (void) Lst_Remove (permits, ln);
  420.     if (permit->permit.addr.s_addr != from->sin_addr.s_addr) {
  421.         ERROR(Invalid address);
  422.     }
  423.     if (verbose) {
  424.         printf ("Received IMPORT from %s\n",
  425.             InetNtoA(permit->permit.addr));
  426.     }
  427.     
  428. #ifndef INSECURE
  429.     /*
  430.      * Make sure the person's not trying to execute as root...
  431.      */
  432.     if (wbPtr->ruid == 0 || wbPtr->euid == 0) {
  433.         printf ("Attempted execution as ROOT\n");
  434.         /*
  435.          * We don't care if this RPC times out...
  436.          */
  437.         Log_Send(LOG_ACCESS, 1, xdr_sockaddr_in, from);
  438.         ERROR(Root execution not allowed);
  439.     }
  440. #endif /* INSECURE */
  441.     /*
  442.      * The effective uid of the caller is encoded in the high word of
  443.      * permit id. We make sure it matches the id in the WayBill
  444.      * to prevent one source of fraud
  445.      */
  446.     permituid = (wbPtr->id >> 16) & 0xffff;
  447.     
  448.     if (wbPtr->euid != permituid) {
  449.         printf ("Mismatched uid's (permit = %d, waybill=%d)\n",
  450.             permituid, wbPtr->euid);
  451.         Log_Send(LOG_ACCESS, 1, xdr_sockaddr_in, from);
  452.         ERROR(Mismatched user IDs);
  453.     }
  454.  
  455.     cp = (char *)&wbPtr[1];
  456.     cwd = cp;
  457.     cp += strlen(cwd) + 1;
  458.     file = cp;
  459.     cp += strlen(file) + 1;
  460.     cp = Customs_Align(cp, char *);
  461.     argv = ImportExtractVector(&cp);
  462.     envp = ImportExtractVector(&cp);
  463.     
  464.     proc = (Process *) malloc (sizeof (Process));
  465.     proc->permit = permit;
  466.     proc->retAddr = *from;
  467.     proc->retAddr.sin_port = wbPtr->port;
  468.  
  469.     Rpc_Return(msg, sizeof("Ok"), (Rpc_Opaque)"Ok");
  470.     
  471.     fflush(stdout);
  472.     proc->pid = fork();
  473.     if (proc->pid == 0) {
  474.         /*
  475.          * Child process:
  476.          * Set std{in,out,err} to send things to and receive things from
  477.          * the remote machine. Files opened for other jobs will close when
  478.          * we exec... Once that is done, attempt to set up the running
  479.          * environment:
  480.          *      1) set both gids
  481.          *      2) install all the groups the caller is in
  482.          *      3) set both uids
  483.          *      4) chdir to the working directory
  484.          *      5) set the umask correctly.
  485.          * Then fork and execute the given command using the passed
  486.          * environment instead of our own. If any of these steps fails,
  487.          * we print an error message for pen pal to read and return a
  488.          * non-zero exit status.
  489.          */
  490.         union wait    status;
  491.         int          cpid;
  492.         int          oldstdout;
  493.  
  494.         /*
  495.          * Reset our priority to 0 since we're just another job now
  496.          */
  497.         setpriority(PRIO_PROCESS, getpid(), 0);
  498.  
  499.         oldstdout = dup(1);
  500.         
  501.         if (sock != 0) {
  502.         dup2 (sock, 0);
  503.         }
  504.         if (sock != 1) {
  505.         dup2 (sock, 1);
  506.         }
  507.         if (sock != 2) {
  508.         dup2 (sock, 2);
  509.         }
  510.         status.w_status = 0;
  511.         
  512.         environ = envp;
  513.         
  514.         if (setregid (wbPtr->rgid, wbPtr->egid) < 0) {
  515.         perror("Couldn't set real/effective group ids");
  516.         status.w_retcode = 1;
  517.         }
  518. #define min(a,b) ((a)<(b)?(a):(b))
  519.         if (setgroups (min(wbPtr->ngroups, NGROUPS), wbPtr->groups) < 0){
  520.         perror("Couldn't set groups");
  521.         status.w_retcode = 2;
  522.         }
  523.         if (setreuid (wbPtr->ruid, wbPtr->euid) < 0) {
  524.         perror("Couldn't set real/effective user ids");
  525.         status.w_retcode = 3;
  526.         }
  527.         if (chdir (cwd) < 0) {
  528.         perror("Couldn't change to current directory");
  529.         printf("cwd = \"%s\"\n", cwd);
  530.         fflush(stdout);
  531.         status.w_retcode = 4;
  532.         }
  533.         umask (wbPtr->umask);
  534.         signal (SIGPIPE, SIG_DFL);
  535.  
  536.         /*
  537.          * Don't want to do anything our parent is doing, so reset
  538.          * the RPC system.
  539.          */
  540.         Rpc_Reset();
  541.         setpgrp(0, getpid());
  542.  
  543.         if (status.w_status == 0) {
  544.         /*
  545.          * If we're still ok, fork and exec the program to
  546.          * be run, then wait for it to finish. We do a bare
  547.          * wait since we will suspend when it suspends, etc.
  548.          * We be a dedicated process...
  549.          */
  550.         cpid = vfork();
  551.         if (cpid == 0) {
  552.             close(oldstdout);
  553.             if (sock > 2) {
  554.             (void)close(sock);
  555.             }
  556.             execvp (file, argv);
  557.             perror("Couldn't exec program");
  558.             _exit(5);
  559.         } else if (cpid < 0) {
  560.             perror("Couldn't fork");
  561.             status.w_retcode = 6;
  562.         }
  563.         }
  564.  
  565.         /*
  566.          * Block all signals we can. Anything we get, our
  567.          * child will get too, and we will exit when it does,
  568.          * so there's no point in our dying without sending
  569.          * a status back, is there?
  570.          */
  571.         sigblock(~0);
  572.  
  573.         /*
  574.          * Substitute new socket for sending log messages and exit
  575.          * statuses.
  576.          */
  577.         udpSocket = Rpc_UdpCreate(FALSE, 0);
  578.  
  579.         /*
  580.          * No need for us to keep the socket open. Also want to print
  581.          * our messages to the log file, so redup the old stdout back to
  582.          * stream 1.
  583.          */
  584.         if (sock != 0) {
  585.         close(0);
  586.         }
  587.         if (sock != 1) {
  588.         close(1);
  589.         }
  590.         if (sock != 2) {
  591.         close(2);
  592.         }
  593.         dup2(oldstdout, 1);
  594.         close(oldstdout);
  595.         
  596.         while (1) {
  597.         Rpc_Stat    rstat;
  598.         char        oob;
  599.         Exit_Data   retVal;
  600.         
  601.         if (status.w_status == 0) {
  602.             /*
  603.              * Haven't got an exit status yet, so wait for one.
  604.              * We block on the wait since we've got nothing better
  605.              * to do.
  606.              */
  607.             int    pid;
  608.             do {
  609.             pid = wait3(&status, WUNTRACED, (struct rusage *)0);
  610.             } while ((pid != cpid) && (pid > 0));
  611.         }
  612.  
  613.         /*
  614.          * Force an EOF-equivalent on the socket on the remote side
  615.          */
  616.         if (send(sock, &oob, 1, MSG_OOB) < 0) {
  617.             perror("sendOOB");
  618.         }
  619.         
  620.         close(sock);
  621.         
  622.         /*
  623.          * Return exit status. We don't really care if the
  624.          * other side receives it. We're very optimistic.
  625.          * They'll find out either by the RPC or by the socket
  626.          * going away...
  627.          */
  628.         if (verbose) {
  629.             printf("Calling %d@%s\n", ntohs(proc->retAddr.sin_port),
  630.                InetNtoA(proc->retAddr.sin_addr));
  631.         }
  632.         
  633.         retVal.id = permit->permit.id;
  634.         retVal.status = status.w_status;
  635.         
  636.         rstat = Rpc_Call(udpSocket, &proc->retAddr,
  637.                  (Rpc_Proc)CUSTOMS_EXIT,
  638.                  sizeof(retVal), (Rpc_Opaque)&retVal,
  639.                  0, (Rpc_Opaque)0,
  640.                  CUSTOMSINT_NRETRY, &retryTimeOut);
  641.         if (rstat != RPC_SUCCESS) {
  642.             Log_Send(LOG_EXITFAIL, 1,
  643.                  xdr_exportpermit, &permit->permit);
  644.         }
  645.         
  646.         if (verbose) {
  647.             if (WIFSIGNALED(status)) {
  648.             printf("%d: signal %d\n", cpid, status.w_termsig);
  649.             } else if (WIFSTOPPED(status)) {
  650.             printf("%d: stopped(%d)\n", cpid, status.w_stopsig);
  651.             } else {
  652.             printf("%d: exit(%d)\n", cpid, status.w_retcode);
  653.             }
  654.             if (rstat != RPC_SUCCESS) {
  655.             printf("EXIT call failed: %s\n",
  656.                    Rpc_ErrorMessage(rstat));
  657.             }
  658.         }
  659.         if (!WIFSTOPPED(status)) {
  660.             /*
  661.              * The process is actually done, so break out of this
  662.              * loop after telling the logger that the job is
  663.              * finished.
  664.              */
  665.             Log_Send(LOG_FINISH, 2,
  666.                  xdr_exportpermit, &permit->permit,
  667.                  xdr_int, &status);
  668.             break;
  669.         } else {
  670.             /*
  671.              * Tell logger the job is just stopped and loop.
  672.              */
  673.             Log_Send(LOG_STOPPED, 1,
  674.                  xdr_exportpermit, &permit->permit);
  675.             status.w_status = 0;
  676.         }
  677.         }
  678.         exit(0);
  679.     } else if (proc->pid == -1) {
  680.         /*
  681.          * Couldn't fork:
  682.          * close everything we just opened and return an error.
  683.          */
  684.         free ((Address) proc);
  685.         free((char *)argv);
  686.         free((char *)envp);
  687.         ERROR(Could not fork);
  688.     } else {
  689.         /*
  690.          * Parent process:
  691.          * Close the socket and start up the child reaper to catch dead
  692.          * children if it isn't going already (it won't be if there were
  693.          * no jobs running before this one).
  694.          */
  695.  
  696.         Rpc_Ignore(sock);
  697.         (void)close(sock);
  698.         if (Lst_IsEmpty (imports)) {
  699.         checkEvent = Rpc_EventCreate (&checkInterval, ImportCheckAll,
  700.                           (Rpc_Opaque)0);
  701.         }
  702.         Lst_AtEnd (imports, (ClientData)proc);
  703.  
  704.         Log_Send(LOG_START, 4,
  705.                xdr_exportpermit, &permit->permit,
  706.                xdr_short, &wbPtr->euid,
  707.                xdr_short, &wbPtr->ruid,
  708.                xdr_strvec, &argv);
  709.         free((char *)argv);
  710.         free((char *)envp);
  711.     }
  712.     }
  713. }
  714.  
  715. /*-
  716.  *-----------------------------------------------------------------------
  717.  * Import_NJobs --
  718.  *    Return the number of imported jobs. This includes not only
  719.  *    currently-running jobs, but potential jobs as well. This is to
  720.  *    keep the quota from being overflowed by requesting enough hosts
  721.  *    to cause this machine to be overallocated before it can send
  722.  *    of an availability packet...Better to overestimate the number
  723.  *    of jobs and have this machine unavailable than to overload this
  724.  *    machine...
  725.  *
  726.  * Results:
  727.  *    The number of jobs.
  728.  *
  729.  * Side Effects:
  730.  *    None.
  731.  *
  732.  *-----------------------------------------------------------------------
  733.  */
  734. Import_NJobs()
  735. {
  736.     return (Lst_Length (imports) + Lst_Length(permits));
  737. }
  738.  
  739. /*-
  740.  *-----------------------------------------------------------------------
  741.  * Import_Init --
  742.  *    Initialize this module.
  743.  *
  744.  * Results:
  745.  *    None.
  746.  *
  747.  * Side Effects:
  748.  *    The imports list is initialized.
  749.  *
  750.  *-----------------------------------------------------------------------
  751.  */
  752. void
  753. Import_Init()
  754. {
  755.     imports = Lst_Init (FALSE);
  756.     permits = Lst_Init (FALSE);
  757.     (void)signal (SIGPIPE, SIG_IGN);
  758.  
  759.     Rpc_ServerCreate(tcpSocket, (Rpc_Proc)CUSTOMS_IMPORT, ImportProcess,
  760.              Swap_WayBill, Rpc_SwapLong, (Rpc_Opaque)0);
  761.     Rpc_ServerCreate(udpSocket, (Rpc_Proc)CUSTOMS_ALLOC, ImportAllocated,
  762.              Swap_ExportPermit, Rpc_SwapLong, (Rpc_Opaque)0);
  763.     Rpc_ServerCreate(udpSocket, (Rpc_Proc)CUSTOMS_KILL, ImportHandleKill,
  764.              Swap_Kill, Rpc_SwapNull, (Rpc_Opaque)0);
  765. }
  766.